export class Set {
  items = {}

  add (value) {
    if ( this.has(value) ) return false

    this.items[value] = value
    return true
  }

  has (value) {
    return this.items.hasOwnProperty(value)
  }

  remove (value) {
    if ( !this.has(value) ) return false

    Reflect.deleteProperty(this.items, value)
    return true
  }

  clear () {
    this.items = {}
  }

  size () {
    return Reflect.ownKeys(this.items).length
  }

  values () {
    return Reflect.ownKeys(this.items)
  }

  union (otherSet) {
    let unionSet = new Set()

    let values = this.values()
    for (const value of values) {
      unionSet.add(value)
    }

    values = otherSet.values()
    for (const value of values) {
      unionSet.add(value)
    }
    
    return unionSet
  }

  intersection (otherSet) {
    let intersectionSet = new Set()

    let values = this.values()
    for (const value of values) {
      if (otherSet.has(value)) intersectionSet.add(value)
    }

    return intersectionSet
  }

  difference (otherSet) {
    let differenceSet = new Set()

    let values = this.values()
    for (const value of values) {
      if (!otherSet.has(value)) differenceSet.add(value)
    }

    return differenceSet
  }

  subset (otherSet) {
    let values = this.values()

    for (const value of values) {
      if (!otherSet.has(value)) return false
    }

    return true
  }
}